package strategy

import (
	"context"
	"errors"

	"gitee.com/leonscript/sally/v2/domain/entity"
)

// AutoApprovalStrategy 自动审批策略类型
type AutoApprovalStrategy string

// 自动审批策略枚举
const (
	// AutoApprovalStrategyAdjacent 相邻策略：相同审批人连续在相邻的节点中出现才触发自动审批
	AutoApprovalStrategyAdjacent AutoApprovalStrategy = "ADJACENT"
	// AutoApprovalStrategyAny 任意策略：审批人只要出现就执行自动审批
	AutoApprovalStrategyAny AutoApprovalStrategy = "ANY"
)

// AutoApprovalResult 自动审批结果
type AutoApprovalResult struct {
	// ShouldAutoApprove 是否应该自动审批
	ShouldAutoApprove bool
	// Reason 自动审批的原因
	Reason string
}

// AutoApprovalStrategyHandler 自动审批策略处理器接口
type AutoApprovalStrategyHandler interface {
	// ShouldAutoApprove 判断是否应该自动审批
	// currentUserID: 当前用户ID（发起人或当前审批人）
	// completedTasks: 已完成的审批任务列表
	// currentNodeAllTasks: 当前节点的所有审批任务列表
	// approvalStrategy: 当前节点的审批策略（OR/AND）
	// nextNodeReviewerTasks: 下一个节点的审批任务列表
	// decisionMaker: 审批决策器，用于调用通用的节点通过判断逻辑
	ShouldAutoApprove(ctx context.Context, currentUserID string, completedTasks []entity.NodeReviewerTask, currentNodeAllTasks []entity.NodeReviewerTask, approvalStrategy entity.ApprovalStrategy, nextNodeReviewerTasks []entity.NodeReviewerTask, decisionMaker NodePassDecisionMaker) AutoApprovalResult
}

// NodePassDecisionMaker 节点通过决策器接口
// 用于解耦自动审批策略与具体的节点通过判断逻辑
type NodePassDecisionMaker interface {
	// WouldNodePassWithUserApproval 判断指定用户的审批是否会导致节点通过
	WouldNodePassWithUserApproval(userID string, allTasks []entity.NodeReviewerTask, approvalStrategy entity.ApprovalStrategy) bool
}

// AdjacentAutoApprovalStrategy 相邻自动审批策略实现
type AdjacentAutoApprovalStrategy struct{}

// ShouldAutoApprove 相邻策略：检查当前用户的审批是否会导致节点通过且当前用户在下一级审批任务中
func (a *AdjacentAutoApprovalStrategy) ShouldAutoApprove(ctx context.Context, currentUserID string, completedTasks []entity.NodeReviewerTask, currentNodeAllTasks []entity.NodeReviewerTask, approvalStrategy entity.ApprovalStrategy, nextNodeReviewerTasks []entity.NodeReviewerTask, decisionMaker NodePassDecisionMaker) AutoApprovalResult {
	// 如果没有下一级审批任务，则不需要自动审批
	if len(nextNodeReviewerTasks) == 0 {
		return AutoApprovalResult{
			ShouldAutoApprove: false,
			Reason:            "没有下一级审批任务",
		}
	}

	// 检查当前用户是否在下一级审批任务中
	currentUserInNextTasks := false
	for _, task := range nextNodeReviewerTasks {
		if task.ReviewerID == currentUserID {
			currentUserInNextTasks = true
			break
		}
	}

	if !currentUserInNextTasks {
		return AutoApprovalResult{
			ShouldAutoApprove: false,
			Reason:            "当前用户不在下一级审批任务中",
		}
	}

	// 使用决策器判断当前用户的审批是否会导致节点通过
	if !decisionMaker.WouldNodePassWithUserApproval(currentUserID, currentNodeAllTasks, approvalStrategy) {
		return AutoApprovalResult{
			ShouldAutoApprove: false,
			Reason:            "当前用户的审批不会导致节点通过",
		}
	}

	return AutoApprovalResult{
		ShouldAutoApprove: true,
		Reason:            "当前用户在下一级审批任务中",
	}
}



// AnyAutoApprovalStrategy 任意自动审批策略实现
type AnyAutoApprovalStrategy struct{}

// ShouldAutoApprove 任意策略：检查当前用户是否在下一级审批任务中，且已完成任务中有通过状态的审批人重合
func (a *AnyAutoApprovalStrategy) ShouldAutoApprove(ctx context.Context, currentUserID string, completedTasks []entity.NodeReviewerTask, currentNodeAllTasks []entity.NodeReviewerTask, approvalStrategy entity.ApprovalStrategy, nextNodeReviewerTasks []entity.NodeReviewerTask, decisionMaker NodePassDecisionMaker) AutoApprovalResult {
	// 如果没有下一级审批任务，则不需要自动审批
	if len(nextNodeReviewerTasks) == 0 {
		return AutoApprovalResult{
			ShouldAutoApprove: false,
			Reason:            "没有下一级审批任务",
		}
	}

	// 创建已完成任务中已审批通过的审批人集合
	completedReviewers := make(map[string]bool)
	for _, task := range completedTasks {
		if task.Status == entity.TaskPassedStatus {
			completedReviewers[task.ReviewerID] = true
		}
	}

	// 检查下一级审批任务中是否有审批人在已完成任务中审批过
	for _, nextTask := range nextNodeReviewerTasks {
		if completedReviewers[nextTask.ReviewerID] {
			return AutoApprovalResult{
				ShouldAutoApprove: true,
				Reason:            "下一级审批任务中的审批人已在之前的节点中审批过",
			}
		}
	}

	return AutoApprovalResult{
		ShouldAutoApprove: false,
		Reason:            "下一级审批任务中的审批人均未在之前的节点中审批过",
	}
}

// AutoApprovalStrategyFactory 自动审批策略工厂
type AutoApprovalStrategyFactory struct{}

// CreateStrategy 根据策略类型创建对应的策略处理器
func (f *AutoApprovalStrategyFactory) CreateStrategy(strategy AutoApprovalStrategy) (AutoApprovalStrategyHandler, error) {
	switch strategy {
	case AutoApprovalStrategyAdjacent, "":
		return &AdjacentAutoApprovalStrategy{}, nil
	case AutoApprovalStrategyAny:
		return &AnyAutoApprovalStrategy{}, nil
	default:
		return nil, errors.New("unsupported auto approval strategy: " + string(strategy))
	}
}
